package com.smile.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.digest.MD5;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.smile.api.OssApi;
import com.smile.commons.file.FileUtils;
import com.smile.commons.gps.RouteFileUtils;
import com.smile.commons.gps.RouteWaypointAirlineFileUtils;
import com.smile.commons.gps.domain.*;
import com.smile.commons.gps.domain.kml.*;
import com.smile.commons.gps.kml.*;
import com.smile.commons.page.R;
import com.smile.file.uitl.MinioUtil;
import com.smile.mapper.DeviceModelMapper;
import com.smile.mapper.DronePayloadMapper;
import com.smile.model.domain.FeisuanDeviceModel;
import com.smile.model.dto.request.GenerateAirlineFileRequestDTO;
import com.smile.model.dto.request.GeneratePlanarAirlineRequestDTO;
import com.smile.model.dto.request.GenerateWaypointActionRequestDTO;
import com.smile.model.dto.request.GenerateWaypointRequestDTO;
import com.smile.model.response.PutFileResponse;
import com.smile.model.response.response.GenerateAirlineFileResponseDTO;
import com.smile.service.PayloadService;
import com.smile.service.mqtt.handler.AbstractServicesHandler;
import com.smile.service.FlightTaskService;
import com.smile.service.entity.drc.HeartBeatData;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import static com.smile.commons.gps.kml.ExecuteRCLostActionEnums.GO_BACK;
import static com.smile.commons.gps.kml.ExitOnRCLostEnums.GO_CONTINUE;

@Service
@Slf4j
public class FlightTaskServiceImpl implements FlightTaskService {

    private static final String XML_HEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";

    private static final String LOCAL_KMZ_FILE_PATH = "file" + File.separator + "kmz" + File.separator;


    @Autowired
    private OssApi ossApi;

    @Autowired
    private DeviceModelMapper deviceModelMapper;
    @Autowired
    private DronePayloadMapper  dronePayloadMapper;

    public static void main(String[] args) throws IOException {
//        System.out.println(new File("file/kmz/57d8f2bbc93540c0b0bb5e91ac37812f.kmz").getAbsolutePath());

//        System.out.println("md5=" + MD5.create().digestHex(new File(new File("file/kmz/57d8f2bbc93540c0b0bb5e91ac37812f.kmz").getAbsolutePath())));

        KmlParams kmlParams = new KmlParams();
        kmlParams.setTemplateType(TemplateTypeEnums.MAPPING2D.getValue());
        kmlParams.setDroneType(100);
        //子类型M4td
        kmlParams.setSubDroneType(1);
        kmlParams.setPayloadType(PayloadTypeEnums.M4TD.getValue());
        kmlParams.setPayloadPosition(PayloadPositionIndexEnums.ZERO.getValue());
        kmlParams.setImageFormat("visable,ir");
        kmlParams.setTakeOffRefPoint("30.249822,119.902248,18.248207");
        kmlParams.setAirlineHeightType(0);
        kmlParams.setGlobalHeight(new BigDecimal("80.0000"));
//        kmlParams.set
        RouteFileUtils.KmlParamsExtension kmlParamsExtension = new RouteFileUtils.KmlParamsExtension();
        kmlParamsExtension.setTakeOffSecurityHeight(new BigDecimal("80.0000"));
        kmlParamsExtension.setGlobalRTHHeight(new BigDecimal("80.0000"));
        kmlParamsExtension.setGlobalTransitionalSpeed(new BigDecimal("18.0000"));

        WaypointHeadingReq waypointHeadingReq = new WaypointHeadingReq();
        waypointHeadingReq.setWaypointHeadingMode(WaypointHeadingModeEnums.FOLLOW_WAYLINE.getValue());
//        waypointHeadingReq.setWaypointHeadingAngle();
        kmlParams.setWaypointHeadingReq(waypointHeadingReq);
        kmlParams.setGimbalPitchMode(GimbalPitchModeEnums.MANUAL.getValue());
        //被摄面
        kmlParams.setGlobalShootHeight(new BigDecimal("80.0000"));

        MappingTypeReq mappingTypeReq = new MappingTypeReq();
        mappingTypeReq.setMargin("30");
        mappingTypeReq.setLensType(LensTypeEnums.LIDAR.getValue());
        mappingTypeReq.setDirection("270");
        mappingTypeReq.setElevationOptimizeEnable(1);
        mappingTypeReq.setCollectionMethod(CollectionMethodEnums.ORTHO.getValue());
        mappingTypeReq.setShootType(ShootTypeEnums.TIME.getValue());
        mappingTypeReq.setMargin("20.00");
        List<CoordinatePointReq> list = new ArrayList<>();
        CoordinatePointReq coordinatePointReq = new CoordinatePointReq();
        coordinatePointReq.setHeight(new BigDecimal("0.0000"));
        coordinatePointReq.setLongitude(new BigDecimal("119.90194887947"));
        coordinatePointReq.setLatitude(new BigDecimal("30.249637104403"));
        list.add(coordinatePointReq);

        CoordinatePointReq coordinatePointReq1 = new CoordinatePointReq();
        coordinatePointReq1.setHeight(new BigDecimal("0.0000"));
        coordinatePointReq1.setLongitude(new BigDecimal("119.901720633915"));
        coordinatePointReq1.setLatitude(new BigDecimal("30.2493112934325"));
        list.add(coordinatePointReq1);

        CoordinatePointReq coordinatePointReq2 = new CoordinatePointReq();
        coordinatePointReq2.setHeight(new BigDecimal("0.0000"));
        coordinatePointReq2.setLongitude(new BigDecimal("119.901933665161"));
        coordinatePointReq2.setLatitude(new BigDecimal("30.2492452520391"));
        list.add(coordinatePointReq2);

        CoordinatePointReq coordinatePointReq3 = new CoordinatePointReq();
        coordinatePointReq3.setHeight(new BigDecimal("0.0000"));
        coordinatePointReq3.setLongitude(new BigDecimal("119.902217704731"));
        coordinatePointReq3.setLatitude(new BigDecimal("30.2496503132285"));
        list.add(coordinatePointReq3);
        mappingTypeReq.setLensType(LensTypeEnums.CAMERA.getValue());

        mappingTypeReq.setOverlapW(80);
        mappingTypeReq.setOverlapH(70);
        mappingTypeReq.setCoordinates(list);
        kmlParams.setMappingTypeReq(mappingTypeReq);
        String fileName = UUID.randomUUID().toString().replaceAll("-", "");
        String s = RouteFileUtils.buildKmz(kmlParamsExtension, fileName, kmlParams);
        System.out.println(s);
    }

    @Override
    public GenerateAirlineFileResponseDTO generateAirlineFile(GenerateAirlineFileRequestDTO generateAirlineFileRequestDTO) throws IOException {


        File file = null;
        String s = null;
        String s1 = null;

        try {
            KmlParams uavRouteReq = new KmlParams();
            if (generateAirlineFileRequestDTO.getAirlineType() == 0) {
                uavRouteReq.setTemplateType("waypoint");
            }
            FeisuanDeviceModel feisuanDeviceModel = deviceModelMapper.selectById(generateAirlineFileRequestDTO.getModelId());
            //这里先写死 主类型是大疆机场3
            if (ObjectUtil.isNotNull(feisuanDeviceModel)) {
                uavRouteReq.setDroneType(Integer.valueOf( feisuanDeviceModel.getType()));
                //子类型M4td
                uavRouteReq.setSubDroneType(Integer.valueOf( feisuanDeviceModel.getSubType()));
                uavRouteReq.setPayloadType(PayloadTypeEnums.M4TD.getValue());
                uavRouteReq.setPayloadPosition(PayloadPositionIndexEnums.ZERO.getValue());
            }else{
                uavRouteReq.setDroneType(100);
                //子类型M4td
                uavRouteReq.setSubDroneType(1);
                uavRouteReq.setPayloadType(PayloadTypeEnums.M4TD.getValue());
                uavRouteReq.setPayloadPosition(PayloadPositionIndexEnums.ZERO.getValue());
            }


//            uavRouteReq.setFinishAction("goHome");

            //    /**
            //     * 0自动返航
            //     * 1返回航线到起始点悬停
            //     * 2退出航线模式
            //     * 3原地降落
            //     */
            //    private Integer outOfControlAction;

//            switch (generateAirlineFileRequestDTO.getOutOfControlAction()) {
//                case 0:
            uavRouteReq.setExecuteRCLostAction(GO_CONTINUE.getValue());
//                    break;
//                case 1:
//                    uavRouteReq.setExecuteRCLostAction(ExecuteRCLostActionEnums.HOVER.getValue());
//                    break;
//                case 2:
//                    break;
//                case 3:
//                    uavRouteReq.setExecuteRCLostAction(ExecuteRCLostActionEnums.LANDING.getValue());
//                    break;
//            }

//            uavRouteReq.setExecuteRCLostAction("goContinue");
            List<String> imageStorage = new ArrayList<>();

            if (generateAirlineFileRequestDTO.getIrType() == 0 ) {
                imageStorage.add(ImageFormatEnums.IR.getValue());
            } else if (generateAirlineFileRequestDTO.getVisableType() == 0 ) {
                imageStorage.add(ImageFormatEnums.VISABLE.getValue());
            }
            uavRouteReq.setImageFormat(String.join(",",imageStorage));


            switch (generateAirlineFileRequestDTO.getAirlineHeightType()) {
                case 0:
                    //相对起飞点高度
                    uavRouteReq.setAirlineHeightType(0);
                    break;
                case 1:
                    //相对地面高度
                    uavRouteReq.setAirlineHeightType(1);
                    break;
                case 2:
                    //海拔高度
                    uavRouteReq.setAirlineHeightType(2);
                    break;
            }

            switch (generateAirlineFileRequestDTO.getFinishAction()) {
                case 0:
                    //自动返航
                    uavRouteReq.setFinishAction(FinishActionEnums.GO_HOME.getValue());
                    break;
                case 1:
                    //返回航线到起始点悬停
                    uavRouteReq.setFinishAction(FinishActionEnums.GOTO_FIRST_WAYPOINT.getValue());
                    break;
                case 2:
                    //退出航线模式
                    uavRouteReq.setFinishAction(FinishActionEnums.NO_ACTION.getValue());
                    break;
                case 3:
                    //原地降落
                    uavRouteReq.setFinishAction(FinishActionEnums.AUTO_LAND.getValue());
                    break;
            }

            uavRouteReq.setExitOnRcLostAction(GO_CONTINUE.getValue());
            uavRouteReq.setGlobalHeight(generateAirlineFileRequestDTO.getGlobalHeight());
            uavRouteReq.setAutoFlightSpeed(generateAirlineFileRequestDTO.getAutoFlightSpeed());


            //TODO 兴趣点 暂时省略


            WaypointTurnReq waypointTurnReq = new WaypointTurnReq();

            System.out.println("wayPointType = " + generateAirlineFileRequestDTO.getWayPointType());

            switch (generateAirlineFileRequestDTO.getWayPointType()) {
                //     * 1. 直线飞行，飞行器点到停
                //     * 2. 平滑过点，提前转弯
                //     * 3. 曲线飞行，飞行器到点停
                //     * 4. 曲线飞行，飞行器过点不停
                case 0:
                    waypointTurnReq.setWaypointTurnMode(GlobalWaypointTurnModeEnums.COORDINATE_TURN.getValue());
                    break;
                case 1:
                    waypointTurnReq.setWaypointTurnMode(GlobalWaypointTurnModeEnums.TO_POINT_AND_STOP_WITH_DISCONTINUITY_CURVATURE.getValue());
                    break;
                case 2:
                    waypointTurnReq.setWaypointTurnMode(GlobalWaypointTurnModeEnums.TO_POINT_AND_PASS_WITH_CONTINUITY_CURVATURE.getValue());
                    waypointTurnReq.setUseStraightLine(1);
                    break;
                case 3:
                    waypointTurnReq.setWaypointTurnMode(GlobalWaypointTurnModeEnums.TO_POINT_AND_STOP_WITH_CONTINUITY_CURVATURE.getValue());
                    break;
                case 4:
                    waypointTurnReq.setWaypointTurnMode(GlobalWaypointTurnModeEnums.TO_POINT_AND_PASS_WITH_CONTINUITY_CURVATURE.getValue());
                    break;
            }

            System.out.println("wayPointTurnMode = " + waypointTurnReq.getWaypointTurnMode());

            //设置为直线飞行，飞行器到点停
            //0：航段轨迹全程为曲线
            //1：航段轨迹尽量贴合两点连线
            waypointTurnReq.setUseStraightLine(1);
            waypointTurnReq.setWaypointTurnDampingDist(1D);


            uavRouteReq.setWaypointTurnReq(waypointTurnReq);
//            uavRouteReq.setGimbalPitchMode(GimbalPitchModeEnums.USE_POINT_SETTING.getValue());
            uavRouteReq.setTakeOffRefPoint(generateAirlineFileRequestDTO.getTakeOffRefPoint());

            //生成航点
            uavRouteReq.setRoutePointList(generateWayPoint(generateAirlineFileRequestDTO.getWayPoints()));


            uavRouteReq.setWaypointTurnReq(waypointTurnReq);
            uavRouteReq.setGimbalPitchMode(GimbalPitchModeEnums.MANUAL.getValue());
            uavRouteReq.setTakeOffRefPoint(generateAirlineFileRequestDTO.getTakeOffRefPoint());

            WaypointHeadingReq waypointHeadingReq = new WaypointHeadingReq();
            System.out.println("attitudeHead = " + generateAirlineFileRequestDTO.getAttitudeHead());
            //0沿航线方向 1手动控制 2锁定当前偏航角
            switch (generateAirlineFileRequestDTO.getAttitudeHead()) {
                case 0:
                    waypointHeadingReq.setWaypointHeadingMode(WaypointHeadingModeEnums.FOLLOW_WAYLINE.getValue());
                    break;
                case 1:
                    waypointHeadingReq.setWaypointHeadingMode(WaypointHeadingModeEnums.MANUALLY.getValue());
                    break;
                case 2:
                    waypointHeadingReq.setWaypointHeadingMode(WaypointHeadingModeEnums.FIXED.getValue());
                    break;
            }
            waypointHeadingReq.setWaypointHeadingAngle(new BigDecimal("0.00"));
            waypointHeadingReq.setWaypointPoiPoint("40.0022,118.6964");

            //TODO 这里的兴趣点目前还是随便添加的
            uavRouteReq.setWaypointHeadingReq(waypointHeadingReq);

            MappingTypeReq mappingTypeReq = new MappingTypeReq();
            mappingTypeReq.setCollectionMethod(CollectionMethodEnums.ORTHO.getValue());
            mappingTypeReq.setLensType(LensTypeEnums.CAMERA.getValue());
            mappingTypeReq.setOverlapH(50);
            mappingTypeReq.setOverlapW(50);
            mappingTypeReq.setElevationOptimizeEnable(0);
            mappingTypeReq.setShootType(ShootTypeEnums.TIME.getValue());
            mappingTypeReq.setDirection("50");
            mappingTypeReq.setMargin("50");


            mappingTypeReq.setCoordinates(new ArrayList<>());

            uavRouteReq.setMappingTypeReq(mappingTypeReq);

            PointActionReq pointActionReq = new PointActionReq();
            pointActionReq.setActionIndex(1);
//            pointActionReq.setHoverTime(5.00d);
            pointActionReq.setAircraftHeading(50d);
            pointActionReq.setTakePhotoType(1);
            pointActionReq.setUseGlobalImageFormat(1);
            pointActionReq.setImageFormat(ImageFormatEnums.ZOOM.getValue());
            pointActionReq.setGimbalPitchRotateAngle(50d);
            pointActionReq.setGimbalYawRotateAngle(50d);
            pointActionReq.setZoom(200d);
            pointActionReq.setStartRecord(Boolean.TRUE);
            pointActionReq.setStopRecord(Boolean.FALSE);
            List<PointActionReq> pointActionReqList = new ArrayList<>();
            pointActionReqList.add(pointActionReq);

            uavRouteReq.setStartActionList(pointActionReqList);

            RouteWaypointAirlineFileUtils.KmlParamsExtension kmlParamsExtension = new RouteWaypointAirlineFileUtils.KmlParamsExtension();
            kmlParamsExtension.setTakeOffSecurityHeight(generateAirlineFileRequestDTO.getTakeOffSecurityHeight());
            kmlParamsExtension.setGlobalRTHHeight(generateAirlineFileRequestDTO.getGlobalRTHHeight());
            kmlParamsExtension.setGlobalTransitionalSpeed(generateAirlineFileRequestDTO.getGlobalTransitionalSpeed());

            String fileName = UUID.randomUUID().toString().replaceAll("-", "");

//            s = RoutePlannerAirlineFileUtils.buildKmz(kmlParamsExtension, fileName, uavRouteReq);
            s = RouteWaypointAirlineFileUtils.buildKmz(kmlParamsExtension, fileName, uavRouteReq);
            file = new File(s);
            s1 = MD5.create().digestHex(file);
        } catch (Exception e) {
            e.printStackTrace();
        }

        MultipartFile multipartFile = FileUtils.fileToMultipartFile(file, s);
//        R<PutFileResponse> putFileResponseR = ossApi.putkmlFile(s, multipartFile);

        MinioUtil minioUtil = new MinioUtil();
//        R<PutFileResponse> putFileResponseR = ossApi.putkmlFile(s, multipartFile);
        Map<String,Object> fileInfo =  minioUtil.uploadFile(multipartFile,"my-bucket","airline");
        if (ObjectUtil.isNotNull(fileInfo)) {
            GenerateAirlineFileResponseDTO generateAirlineFileResponseDTO = new GenerateAirlineFileResponseDTO();

//            Map<String, Object> fileInfo = minioUtil.uploadFile(multipartFile,"my-bucket","zip");
            generateAirlineFileResponseDTO.setUrl(fileInfo.get("url").toString());
            generateAirlineFileResponseDTO.setETag(s1);
            generateAirlineFileResponseDTO.setMd5(s1);
            return generateAirlineFileResponseDTO;

        }else{
            throw new RuntimeException("航线文件保存失败");
        }


//        if (ObjectUtil.isNotNull(putFileResponseR) && ObjectUtil.isNotNull(putFileResponseR.getData())) {
////            String s1 = putFileResponseR.getData().getUrl().replaceAll("\\\\", "/");
////            System.out.println("url=" + putFileResponseR.getData().getUrl());
//            GenerateAirlineFileResponseDTO generateAirlineFileResponseDTO = new GenerateAirlineFileResponseDTO();
//            generateAirlineFileResponseDTO.setUrl(putFileResponseR.getData().getUrl());
//            generateAirlineFileResponseDTO.setETag(putFileResponseR.getData().getETag());
//            generateAirlineFileResponseDTO.setMd5(s1);
//            return generateAirlineFileResponseDTO;
//        } else {
////            log.info("执行生成航线文件操作失败,操作用户id为{},requestId={}",
////                    StpUtil.getLoginId(), RequestIdUtils.get());
//            throw new RuntimeException("航线文件保存失败");
//        }
    }

    @Override
    public GenerateAirlineFileResponseDTO generatePlanarAirline(GeneratePlanarAirlineRequestDTO generatePlanarAirlineRequestDTO) throws IOException {
        try {
            KmlParams kmlParams = new KmlParams();
            kmlParams.setTemplateType(TemplateTypeEnums.MAPPING2D.getValue());
            kmlParams.setDroneType(100);
            //子类型M4td
            kmlParams.setSubDroneType(1);
            kmlParams.setPayloadType(PayloadTypeEnums.M4TD.getValue());
            kmlParams.setPayloadPosition(PayloadPositionIndexEnums.ZERO.getValue());
            if (generatePlanarAirlineRequestDTO.getIrTypeSupport() == 1 && generatePlanarAirlineRequestDTO.getWideTypeSupport() == 1) {
                kmlParams.setImageFormat("wide,ir");
            } else {
                if (generatePlanarAirlineRequestDTO.getIrTypeSupport() == 1) {
                    kmlParams.setImageFormat("ir");
                }
                if (generatePlanarAirlineRequestDTO.getWideTypeSupport() == 1) {
                    kmlParams.setImageFormat("wide");
                }
            }
            kmlParams.setTakeOffRefPoint(generatePlanarAirlineRequestDTO.getTakeOffRefPoint());
            kmlParams.setAirlineHeightType(generatePlanarAirlineRequestDTO.getHeightMode());
            kmlParams.setGlobalHeight(generatePlanarAirlineRequestDTO.getHeight());
            kmlParams.setAutoFlightSpeed(generatePlanarAirlineRequestDTO.getAutoFlightSpeed());
            //        kmlParams.set
            RouteFileUtils.KmlParamsExtension kmlParamsExtension = new RouteFileUtils.KmlParamsExtension();
            kmlParamsExtension.setTakeOffSecurityHeight(generatePlanarAirlineRequestDTO.getTakeOffSecurityHeight());
            kmlParamsExtension.setGlobalRTHHeight(generatePlanarAirlineRequestDTO.getHeight());
            kmlParamsExtension.setGlobalTransitionalSpeed(generatePlanarAirlineRequestDTO.getGlobalTransitionalSpeed());

            WaypointHeadingReq waypointHeadingReq = new WaypointHeadingReq();


            //    /**
            //     * 偏航角度
            //     */
            //    private String waypointHeadingAngle;
            //
            //    /**
            //     * 0 沿航线方向
            //     * 1 手动控制
            //     */
            //    private Integer waypointHeadingMode;

            if (generatePlanarAirlineRequestDTO.getWaypointHeadingMode() == 0) {
                waypointHeadingReq.setWaypointHeadingMode(WaypointHeadingModeEnums.FOLLOW_WAYLINE.getValue());
            } else {
                waypointHeadingReq.setWaypointHeadingMode(WaypointHeadingModeEnums.MANUALLY.getValue());
                waypointHeadingReq.setWaypointHeadingAngle(generatePlanarAirlineRequestDTO.getWaypointHeadingAngle());
            }

//        waypointHeadingReq.setWaypointHeadingAngle();
            kmlParams.setWaypointHeadingReq(waypointHeadingReq);
            kmlParams.setGimbalPitchMode(GimbalPitchModeEnums.MANUAL.getValue());
            //被摄面
            kmlParams.setGlobalShootHeight(generatePlanarAirlineRequestDTO.getGlobalShootHeight());
            switch (generatePlanarAirlineRequestDTO.getFinishAction()) {
                //     * 0自动返航
                //     * 1返回航线到起始点悬停
                //     * 2退出航线模式
                //     * 3原地降落
                case 0:
                    kmlParams.setFinishAction(FinishActionEnums.GO_HOME.getValue());
                    break;
                case 1:
                    kmlParams.setFinishAction(FinishActionEnums.GOTO_FIRST_WAYPOINT.getValue());
                    break;
                case 2:
                    kmlParams.setFinishAction(FinishActionEnums.NO_ACTION.getValue());
                    break;
                case 3:
                    kmlParams.setFinishAction(FinishActionEnums.AUTO_LAND.getValue());
            }
            MappingTypeReq mappingTypeReq = new MappingTypeReq();
            mappingTypeReq.setMargin(generatePlanarAirlineRequestDTO.getMargin().toString());
            mappingTypeReq.setLensType(LensTypeEnums.LIDAR.getValue());
            mappingTypeReq.setDirection(generatePlanarAirlineRequestDTO.getDirection().toString());
            mappingTypeReq.setElevationOptimizeEnable(generatePlanarAirlineRequestDTO.getElevationOptimizeEnable());
            mappingTypeReq.setCollectionMethod(CollectionMethodEnums.ORTHO.getValue());
            switch (generatePlanarAirlineRequestDTO.getShootType()) {
                case 0:
                    mappingTypeReq.setShootType(ShootTypeEnums.TIME.getValue());
                    break;
                case 1:
                    mappingTypeReq.setShootType(ShootTypeEnums.DISTANCE.getDescription());
                    break;
            }
            mappingTypeReq.setMargin(generatePlanarAirlineRequestDTO.getMargin().toString());
            mappingTypeReq.setLensType(LensTypeEnums.CAMERA.getValue());

            mappingTypeReq.setOverlapW(generatePlanarAirlineRequestDTO.getOverlapW());
            mappingTypeReq.setOverlapH(generatePlanarAirlineRequestDTO.getOverlapH());
            mappingTypeReq.setCoordinates(BeanUtil.copyToList(generatePlanarAirlineRequestDTO.getCoordinatePointReqList(), CoordinatePointReq.class));
            kmlParams.setMappingTypeReq(mappingTypeReq);
            String fileName = UUID.randomUUID().toString().replaceAll("-", "");
            String s = RouteFileUtils.buildKmz(kmlParamsExtension, fileName, kmlParams);
            File file = new File(s);
            String s1 = MD5.create().digestHex(file);

            MultipartFile multipartFile = FileUtils.fileToMultipartFile(file, s);
            R<PutFileResponse> putFileResponseR = ossApi.putkmlFile(s, multipartFile);
            if (ObjectUtil.isNotNull(putFileResponseR) && ObjectUtil.isNotNull(putFileResponseR.getData())) {
//            String s1 = putFileResponseR.getData().getUrl().replaceAll("\\\\", "/");
//            System.out.println("url=" + putFileResponseR.getData().getUrl());
                GenerateAirlineFileResponseDTO generateAirlineFileResponseDTO = new GenerateAirlineFileResponseDTO();
                generateAirlineFileResponseDTO.setUrl(putFileResponseR.getData().getUrl());
                generateAirlineFileResponseDTO.setETag(putFileResponseR.getData().getETag());
                generateAirlineFileResponseDTO.setMd5(s1);
                System.out.println(generateAirlineFileResponseDTO);
                return generateAirlineFileResponseDTO;
//            return;
            } else {
//            log.info("执行生成航线文件操作失败,操作用户id为{},requestId={}",
//                    StpUtil.getLoginId(), RequestIdUtils.get());
                throw new RuntimeException("航线文件保存失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    public List<RoutePointInfo> generateWayPoint(List<GenerateWaypointRequestDTO> wayPoints) {


        Stack<Integer> stack = new Stack<>();

        AtomicInteger index = new AtomicInteger(0);

        List<RoutePointInfo> collect = wayPoints.stream().map(wayPoint -> {

            AtomicInteger actionIndex = new AtomicInteger(0);
            RoutePointInfo routePointReq = new RoutePointInfo();

            //TODO
            routePointReq.setRoutePointIndex(index.getAndIncrement());


            routePointReq.setLongitude(wayPoint.getLongitude().doubleValue());
            routePointReq.setLatitude(wayPoint.getLatitude().doubleValue());
            routePointReq.setHeight(wayPoint.getHeight());
            routePointReq.setSpeed(wayPoint.getWaypointSpeed().doubleValue());

//            routePointReq.setWaypointTurnReq(waypointTurnReq);
//            routePointReq.setGimbalPitchAngle(50D);

            WaypointHeadingReq waypointHeadingReq = new WaypointHeadingReq();
            if(ObjectUtil.isNull(wayPoint.getWaypointSpeedFollow())) {
                routePointReq.setUseGlobalSpeed("0");
            }else{
                switch (wayPoint.getWaypointSpeedFollow()) {
                    case 0:
                        routePointReq.setUseGlobalSpeed("0");
                        break;
                    case 1:
                        routePointReq.setUseGlobalSpeed("1");
                        break;
                }
            }

                if(ObjectUtil.isNull(wayPoint.getHeightFollow())) {
                    routePointReq.setUseGlobalHeight("0");
                }else {
                    switch (wayPoint.getHeightFollow()) {
                        case 0:
                            routePointReq.setUseGlobalHeight("0");
                            break;
                        case 1:
                            routePointReq.setUseGlobalHeight("1");
                            break;
                    }
                }

            //设置偏航角模式
            switch (wayPoint.getAttitudeHead()) {
                case 0:
                    //沿航线方向
                    waypointHeadingReq.setWaypointHeadingMode(WaypointHeadingModeEnums.FOLLOW_WAYLINE.getValue());
                    break;
                case 1:
                    //手动控制
                    waypointHeadingReq.setWaypointHeadingMode(WaypointHeadingModeEnums.MANUALLY.getValue());
                    break;
                case 2:
                    //锁定当前偏航角
                    waypointHeadingReq.setWaypointHeadingMode(WaypointHeadingModeEnums.FIXED.getValue());
                    break;
            }
            waypointHeadingReq.setWaypointHeadingAngle(new BigDecimal("0.00"));
            //兴趣点这个先随便设置下
            waypointHeadingReq.setWaypointPoiPoint("39.596849155,118.184556104");

            Map<Integer, Integer> map = new HashMap<>();
            wayPoint.getActions().forEach(i -> {
                map.put(i.getActionType(), i.getActionValue());
            });

//            wayPoints.forEach(i -> {
//                switch (i) {
//                    case 1:
//
//                }
//            });

            //TODO
//            PointActionReq pointActionReq = new PointActionReq();

            List<PointActionReq> list = new ArrayList<>();


            AtomicReference<Boolean> flag = new AtomicReference<>(false);

            if (wayPoint.getImageFormat() == 0) {
                routePointReq.setImageFormat(ImageFormatEnums.WIDE.getValue());
            } else if (wayPoint.getImageFormat() == 1) {
                routePointReq.setImageFormat(ImageFormatEnums.ZOOM.getValue());
            } else {
                routePointReq.setImageFormat(ImageFormatEnums.IR.getValue());
            }

            wayPoint.getActions().forEach(i -> {


                switch (i.getActionType()) {
                    //悬停
                    case 1:
                        PointActionReq pointActionReq = new PointActionReq();
                        pointActionReq.setHoverTime(map.get(1).doubleValue());
                        pointActionReq.setActionIndex(actionIndex.getAndIncrement());
                        list.add(pointActionReq);
                        break;
                    //偏航角
                    case 2:
                        PointActionReq pointActionReq1 = new PointActionReq();
                        pointActionReq1.setActionIndex(actionIndex.getAndIncrement());
                        pointActionReq1.setAircraftHeading(map.get(2).doubleValue());
                        list.add(pointActionReq1);
                        break;
                    //俯仰角
                    case 3:
                        PointActionReq pointActionReq3 = new PointActionReq();
                        pointActionReq3.setActionIndex(actionIndex.getAndIncrement());
                        pointActionReq3.setGimbalPitchRotateAngle(map.get(3).doubleValue());
                        list.add(pointActionReq3);
                        break;
                    //普通拍照
                    case 4:
                        PointActionReq pointActionReq4 = new PointActionReq();
                        pointActionReq4.setActionIndex(actionIndex.getAndIncrement());
                        pointActionReq4.setTakePhotoType(0);
                        pointActionReq4.setUseGlobalImageFormat(1);
                        //0广角 1变焦

                        if (wayPoint.getImageFormat() == 0) {
                            pointActionReq4.setImageFormat(ImageFormatEnums.WIDE.getValue());
                        } else if (wayPoint.getImageFormat() == 1) {
                            pointActionReq4.setImageFormat(ImageFormatEnums.ZOOM.getValue());
                        } else {
                            pointActionReq4.setImageFormat(ImageFormatEnums.IR.getValue());
                        }

                        list.add(pointActionReq4);
                        break;
                    //全景拍照
                    case 5:
                        PointActionReq pointActionReq5 = new PointActionReq();
                        pointActionReq5.setActionIndex(actionIndex.getAndIncrement());
                        pointActionReq5.setTakePhotoType(1);
                        pointActionReq5.setUseGlobalImageFormat(0);

                        if (wayPoint.getImageFormat() == 0) {
                            pointActionReq5.setImageFormat(ImageFormatEnums.WIDE.getValue());
                        } else if (wayPoint.getImageFormat() == 1) {
                            pointActionReq5.setImageFormat(ImageFormatEnums.ZOOM.getValue());
                        } else {
                            pointActionReq5.setImageFormat(ImageFormatEnums.IR.getValue());
                        }

                        list.add(pointActionReq5);
                        break;
                    //开始录像
                    case 6:
                        PointActionReq pointActionReq6 = new PointActionReq();
                        pointActionReq6.setStartRecord(Boolean.TRUE);

                        if (wayPoint.getImageFormat() == 0) {
                            pointActionReq6.setImageFormat(ImageFormatEnums.WIDE.getValue());
                        } else if (wayPoint.getImageFormat() == 1) {
                            pointActionReq6.setImageFormat(ImageFormatEnums.ZOOM.getValue());
                        } else {
                            pointActionReq6.setImageFormat(ImageFormatEnums.IR.getValue());
                        }

                        pointActionReq6.setActionIndex(actionIndex.getAndIncrement());
                        pointActionReq6.setUseGlobalImageFormat(1);
                        list.add(pointActionReq6);
                        break;
                    //焦距
                    case 7:
                        PointActionReq pointActionReq7 = new PointActionReq();
                        pointActionReq7.setZoom(map.get(7).doubleValue());
                        pointActionReq7.setActionIndex(actionIndex.getAndIncrement());
                        list.add(pointActionReq7);
                        break;
                    //结束录像
                    case 8:
                        PointActionReq pointActionReq8 = new PointActionReq();
                        pointActionReq8.setStopRecord(Boolean.TRUE);
                        pointActionReq8.setActionIndex(actionIndex.getAndIncrement());

                        if (wayPoint.getImageFormat() == 0) {
                            pointActionReq8.setImageFormat(ImageFormatEnums.WIDE.getValue());
                        } else if (wayPoint.getImageFormat() == 1) {
                            pointActionReq8.setImageFormat(ImageFormatEnums.ZOOM.getValue());
                        } else {
                            pointActionReq8.setImageFormat(ImageFormatEnums.IR.getValue());
                        }

                        list.add(pointActionReq8);
                        break;
                    //等距拍照
                    case 9:
                        routePointReq.setDistanceInterval(map.get(9).doubleValue());

                        flag.set(true);
                        if (flag.get()) {
                            stack.add(wayPoint.getIndex());
                        }

//                        PointActionReq pointActionReq9 = new PointActionReq();
//                        pointActionReq9.setActionIndex(actionIndex.getAndIncrement());
//                        pointActionReq9.setTakePhotoType(0);
//                        pointActionReq9.setUseGlobalImageFormat(1);
//                        //0广角 1变焦
//
//                        if (wayPoint.getImageFormat() == 0) {
//                            pointActionReq9.setImageFormat(ImageFormatEnums.WIDE.getValue());
//                        } else if (wayPoint.getImageFormat() == 1) {
//                            pointActionReq9.setImageFormat(ImageFormatEnums.ZOOM.getValue());
//                        } else {
//                            pointActionReq9.setImageFormat(ImageFormatEnums.IR.getValue());
//                        }
//
//                        list.add(pointActionReq9);

                        break;
                    //等时拍照
                    case 10:
                        //等时拍照间隔时间 单位s
                        routePointReq.setTimeInterval(map.get(10).doubleValue());
                        flag.set(true);
                        if (flag.get()) {
                            stack.add(wayPoint.getIndex());
                        }

                        PointActionReq pointActionReq10 = new PointActionReq();
                        pointActionReq10.setActionIndex(actionIndex.getAndIncrement());
                        pointActionReq10.setTakePhotoType(0);
                        pointActionReq10.setUseGlobalImageFormat(1);
                        //0广角 1变焦

//                        if (wayPoint.getImageFormat() == 0) {
//                            pointActionReq10.setImageFormat(ImageFormatEnums.WIDE.getValue());
//                        } else if (wayPoint.getImageFormat() == 1) {
//                            pointActionReq10.setImageFormat(ImageFormatEnums.ZOOM.getValue());
//                        } else {
//                            pointActionReq10.setImageFormat(ImageFormatEnums.IR.getValue());
//                        }
//
//                        list.add(pointActionReq10);

                        break;
                    //停止间隔拍照
                    case 11:
                        if (!stack.isEmpty()) {
                            //停止间隔拍照航点编号
                            routePointReq.setEndIntervalRouteIndex(stack.pop());
                        }
                        break;


                }
            });

//            list.add(pointActionReq);

            //TODO
//            routePointReq.setActions(createPointAction(wayPoint.getActionIndex(), wayPoint.getActions(), wayPoint.getImageFormat()));
            routePointReq.setActions(list);
            routePointReq.setWaypointHeadingReq(waypointHeadingReq);

            return routePointReq;
        }).collect(Collectors.toList());


        return collect;
    }

    AtomicInteger count = new AtomicInteger();

    public List<PointActionReq> createPointAction(Integer actionIndex, List<GenerateWaypointActionRequestDTO> actions, Integer imageFormat) {
//        PointActionReq pointActionReq = new PointActionReq();
//        pointActionReq.setActionIndex(actionIndex);
        List<PointActionReq> collect = actions.stream().map(action -> {
            PointActionReq pointActionReq = new PointActionReq();
            pointActionReq.setActionIndex(count.incrementAndGet());


            //TODO
//            if (action.getActionType() == 0) {
//                pointActionReq.setImageFormat(ImageFormatEnums.WIDE.getValue());
//            }
//
//            if (action.getActionType() == 1) {
//                pointActionReq.setHoverTime(action.getActionValue().doubleValue());
//            }
//
//            if (action.getActionType() == 2) {
//                //飞行器目标偏航角
//                pointActionReq.setAircraftHeading(action.getActionValue().doubleValue());
//            }
//
//            if (action.getActionType() == 3) {
//                pointActionReq.setUseGlobalImageFormat(1);
//            }
//
//            if (action.getActionType() == 4) {
//                pointActionReq.setTakePhotoType(1);
//            }
//
//            if (action.getActionType() == 5) {
//                pointActionReq.setStartRecord(Boolean.TRUE);
//            }
//
//            if (action.getActionType() == 6) {
//                pointActionReq.setZoom(action.getActionValue().doubleValue());
//            }
//
//            if (action.getActionType() == 7) {
//                pointActionReq.setStartRecord(Boolean.FALSE);
//            }

            return pointActionReq;
        }).collect(Collectors.toList());


        return collect;
    }

    public RoutePointInfo createRoutePointReq(Integer index, WaypointHeadingReq waypointHeadingReq, WaypointTurnReq waypointTurnReq, Double longitude, Double latitude, Double height) {
        RoutePointInfo routePointReq = new RoutePointInfo();
        routePointReq.setRoutePointIndex(index);
        routePointReq.setLongitude(longitude);
        routePointReq.setLatitude(latitude);
        routePointReq.setHeight(new BigDecimal(height.toString()));
        routePointReq.setSpeed(20d);
        routePointReq.setWaypointHeadingReq(waypointHeadingReq);
        routePointReq.setWaypointTurnReq(waypointTurnReq);
        routePointReq.setGimbalPitchAngle(50D);


        PointActionReq pointActionReq = new PointActionReq();
        pointActionReq.setActionIndex(1);
//        pointActionReq.setHoverTime(5.00d);
        pointActionReq.setAircraftHeading(108.14303588867188);
        pointActionReq.setTakePhotoType(1);
        pointActionReq.setUseGlobalImageFormat(1);
        pointActionReq.setImageFormat(ImageFormatEnums.ZOOM.getValue());
        pointActionReq.setGimbalPitchRotateAngle(50d);
        pointActionReq.setGimbalYawRotateAngle(50d);
        pointActionReq.setZoom(200d);
        pointActionReq.setStartRecord(Boolean.TRUE);
        pointActionReq.setStopRecord(Boolean.FALSE);
        List<PointActionReq> pointActionReqList = new ArrayList<>();
        pointActionReqList.add(pointActionReq);
        routePointReq.setActions(pointActionReqList);
        routePointReq.setTimeInterval(5d);
        routePointReq.setDistanceInterval(5d);
        routePointReq.setEndIntervalRouteIndex(3);
        return routePointReq;
    }

    private static void buildKmlParams(KmlParams kmlParams, KmlInfo kmlInfo) {
        KmlFolder folder = kmlInfo.getDocument().getFolder();
        kmlParams.setGlobalHeight(new BigDecimal(kmlInfo.getDocument().getKmlMissionConfig().getGlobalRTHHeight()));
        kmlParams.setAutoFlightSpeed(new BigDecimal(folder.getAutoFlightSpeed()));

        WaypointHeadingReq waypointHeadingReq = new WaypointHeadingReq();
        waypointHeadingReq.setWaypointHeadingMode(folder.getGlobalWaypointHeadingParam().getWaypointHeadingMode());
        waypointHeadingReq.setWaypointHeadingAngle(StringUtils.isNotBlank(folder.getGlobalWaypointHeadingParam().getWaypointHeadingAngle()) ?
                new BigDecimal(folder.getGlobalWaypointHeadingParam().getWaypointHeadingAngle()) : null);
        waypointHeadingReq.setWaypointPoiPoint(StringUtils.isNotBlank(folder.getGlobalWaypointHeadingParam().getWaypointPoiPoint()) ? folder.getGlobalWaypointHeadingParam().getWaypointPoiPoint() : null);
        kmlParams.setWaypointHeadingReq(waypointHeadingReq);

        WaypointTurnReq waypointTurnReq = new WaypointTurnReq();
        waypointTurnReq.setWaypointTurnMode(folder.getGlobalWaypointTurnMode());
        waypointTurnReq.setUseStraightLine(StringUtils.isNotBlank(folder.getGlobalUseStraightLine()) ? Integer.valueOf(folder.getGlobalUseStraightLine()) : null);

        kmlParams.setWaypointTurnReq(waypointTurnReq);
        kmlParams.setGimbalPitchMode(folder.getGimbalPitchMode());
        kmlParams.setPayloadPosition(Integer.valueOf(kmlInfo.getDocument().getKmlMissionConfig().getPayloadInfo().getPayloadPositionIndex()));
        kmlParams.setImageFormat(folder.getPayloadParam().getImageFormat());
    }

    private void handleRouteUpdate(KmlInfo kmlInfo, UavRouteReq uavRouteReq, String fileType, KmlParams kmlParams) {
        if (StringUtils.isNotBlank(uavRouteReq.getFinishAction())) {
            kmlInfo.getDocument().getKmlMissionConfig().setFinishAction(uavRouteReq.getFinishAction());
        }
        if (StringUtils.isNotBlank(uavRouteReq.getExitOnRcLostAction())) {
            kmlInfo.getDocument().getKmlMissionConfig().setExitOnRCLost(ExitOnRCLostEnums.EXECUTE_LOST_ACTION.getValue());
            kmlInfo.getDocument().getKmlMissionConfig().setExecuteRCLostAction(uavRouteReq.getExitOnRcLostAction());
        }
        if (CollectionUtil.isNotEmpty(uavRouteReq.getRoutePointList())) {
            List<KmlPlacemark> placemarkList = new ArrayList<>();
            for (RoutePointReq routePointReq : uavRouteReq.getRoutePointList()) {
                RoutePointInfo routePointInfo = BeanUtil.copyProperties(routePointReq, RoutePointInfo.class);
                KmlPlacemark kmlPlacemark = RouteFileUtils.buildKmlPlacemark(routePointInfo, kmlParams, fileType);
                placemarkList.add(kmlPlacemark);
            }
            kmlInfo.getDocument().getFolder().setPlacemarkList(placemarkList);
        }
    }

    @Autowired
    private AbstractServicesHandler abstractServicesHandler;

    /**
     * 执行巡警
     */
    public void heartbeat() {
        JSONObject jsonObject = new JSONObject();
        HeartBeatData heartBeatData = new HeartBeatData();
        heartBeatData.setTimestamp(System.currentTimeMillis());
        jsonObject.put("method", "heart_beat");
        System.out.println(jsonObject.toJSONString());
        jsonObject.put("data", heartBeatData);
        try {
            abstractServicesHandler.process(jsonObject.toJSONString());
        } catch (MqttException e) {
            throw new RuntimeException(e);
        }
    }

}
